#include "../../include/Dict/EnRecommander.h"
#include <cstdlib>
#include "../../include/Dict/En_distance.h"

#include <string>
#include <string.h>
#include <fstream>
#include <iostream>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <set>
#include <dirent.h>
#include <sstream>

using std::cin;
using std::cout;
using std::endl;
using std::ifstream;
using std::ios;
using std::istringstream;
using std::ofstream;
using std::pair;
using std::set;
using std::string;
using std::unordered_map;
using std::unordered_set;
using std::vector;

EnRecommander::EnRecommander()
{
    read_dict("../data/dictionary.data"); // 文件路径待替换
}

void EnRecommander::read_dict(const string &filename)
{
    ifstream ifs1(filename);
    if (!ifs1)
    {
        cout << "ifstream open " << filename << "failed" << endl;
    }

    string line;
    string word;
    string num;
    size_t line_no = 0;
    while (getline(ifs1, line))
    {

        istringstream iss(line);

        iss >> word;
        iss >> num;
        _wordFrequency.push_back(pair<string, int>(word, stoi(num)));

        for (auto &ch : word)
        {
            _index[ch].insert(line_no);
        }

        line_no++;
    }

    /* ofstream ofs("../data/index.data"); */
    /* if (!ofs) */
    /* { */
    /*     cout << "ifstream open index.data failed" << endl; */
    /* } */

    /* for (auto &elem : _index) */
    /* { */
    /*     ofs << elem.first << "     "; */
    /*     for (auto &index : elem.second) */
    /*     { */
    /*         ofs << index << "  "; */
    /*     } */
    /*     ofs << endl; */
    /* } */
}

string EnRecommander::recommander(const string &queryWord)
{
    unordered_set<int> all_line; // 为加快查询速度并防止行号冲突采用unorder_set
    string copy_word=queryWord;
    for (auto &ch : copy_word)
    {
        if(isupper(ch))
        {
            ch=tolower(ch);
        }
        //cout << ch << endl;
        for (auto &lineNum : _index[ch])
        {
            
            all_line.insert(lineNum); // 拆解搜索词,获得所有字母的所在行的并集
        }
    }

    struct Candidate
    {
        int dist;
        int frequency;
        string word;
    };

    struct MyCompare
    {

        bool operator()(const Candidate &a, const Candidate &b) const
        {
            if (a.dist != b.dist)
            {
                return (a.dist - b.dist) < 0 ? true : false;
            }
            else if (a.frequency != b.frequency)
            {
                return a.frequency < b.frequency;
            }
            else
            {
                return a.word > b.word;
            }
        }
    };

    set<Candidate, MyCompare> candidate; // 储存候选词,及距离和频次

    int dist = 0; // 记录最短距离

    Candidate candi;
    for (auto &lineNum : all_line) // 获取并集中的每一个行号
    {
        string candi_word = _wordFrequency[lineNum].first;
        dist = EeditDistance(candi_word, copy_word);

        candi.frequency = _wordFrequency[lineNum].second;
        candi.dist = dist;
        candi.word = candi_word;
        candidate.insert(candi);
        /* cout<<dist<<"  "<<candi_word<<"  "<<candi.frequency<<endl; */
    }

    /* for(auto &elem :candidate) */
    /* { */
    /*         cout<<elem.dist<<"  "<<elem.word<<"  "<<elem.frequency<<endl; */

    /* } */

    vector<string> recommander_word;

    auto it = candidate.begin();

    for (int i = 0; i < 5; i++)
    {
        recommander_word.push_back(it->word);
        it++;
    }

    json jsonMsg;
    jsonMsg["keywords"] = recommander_word;

    return jsonMsg.dump();
}

/* void test01(){ */

/*     vector<string> result; */
/*     EnRecommander enr; */
/*     enr.read_dict("./data/dictionary.data");//文件路径待替换 */

/*     string qword; */
/*     cin>>qword; */
/* //    result=enr.recommander(qword); */

/*     for(auto &word :result) */
/*     { */
/*         cout<<word<<endl; */
/*     } */
/* } */

/* int main() */
/* { */
/*     test01(); */
/*     return 0; */
/* } */
